#pragma once
#include <vector>
#include <algorithm> // For remove(), lower_bound()
#include <iostream>

class Range {
public:

    // ---------------------------------------------------------------------------
    // Constructor / Destructors
    // ---------------------------------------------------------------------------

    // ---------------------------------------------------------------------------
    //
    // FUNCTION: Constructor
    //
    // DESCRIPTION: Builds a Range object.
    //
    // INPUTS:
    // - x: The starting range, inclusive.
    // - y: The ending range, inclusive.
    // 
    // ---------------------------------------------------------------------------
    Range(int x, int y);
    Range();
    ~Range(void);

    // ---------------------------------------------------------------------------
    // Public Functions
    // ---------------------------------------------------------------------------

    // ---------------------------------------------------------------------------
    //
    // FUNCTION: getStart
    //
    // DESCRIPTION: Returns the value of the private variable Start
    // 
    // ---------------------------------------------------------------------------
    int getStart();

    // ---------------------------------------------------------------------------
    //
    // FUNCTION: getEnd
    //
    // DESCRIPTION: Returns the value of the private variable End
    // 
    // ---------------------------------------------------------------------------
    int getEnd();

    // ---------------------------------------------------------------------------
    //
    // FUNCTION: Contains
    //
    // DESCRIPTION: Determines if this range object contains the argument x.
    //
    // INPUTS: 
    // - x: The value to check if this range contains.
    // 
    // ---------------------------------------------------------------------------
    bool Contains(int x);

    // ---------------------------------------------------------------------------
    //
    // FUNCTION: Contains
    //
    // DESCRIPTION: Determines if this range object contains the range [x, y].
    //
    // INPUTS:
    // - x: The x value of the range to check.
    // - y: The y value of the range to check.
    // 
    // ---------------------------------------------------------------------------
    bool Contains(int x, int y);

    // ---------------------------------------------------------------------------
    //
    // FUNCTION: Add
    //
    // DESCRIPTION: Adds the range [x, y] to this range object.
    //
    // INPUTS:
    // - x: The x value of the range to add.
    // - y: The y value of the range to add.
    // 
    // ---------------------------------------------------------------------------
    void Add(int x, int y);

    // ---------------------------------------------------------------------------
    //
    // FUNCTION: Remove
    //
    // DESCRIPTION: Removes the range [x, y] from this range object.
    //
    // INPUTS:
    // - x: The x value of the range to remove.
    // - y: The y value of the range to remove.
    // 
    // ---------------------------------------------------------------------------
    void Remove(int x, int y);

private:
    // Storage container for the range
    std::vector<int> r;

    // Start of the range, inclusive
    int start;
    // End of the range, inclusive
    int end;

    // ---------------------------------------------------------------------------
    // Private Functions
    // ---------------------------------------------------------------------------

    // ---------------------------------------------------------------------------
    //
    // FUNCTION: updateEnds
    //
    // DESCRIPTION: Updates the private variables Start and End.
    //
    // INPUTS: 
    // - x: The value to assign to Start.
    // - y: The value to assign to End.
    // 
    // ---------------------------------------------------------------------------
    void updateEnds(int x, int y);

    // ---------------------------------------------------------------------------
    //
    // FUNCTION: Populate
    //
    // DESCRIPTION: Populates this range object with integer values ranging from
    //              Start to End.
    // 
    // ---------------------------------------------------------------------------
    void Populate();

    // ---------------------------------------------------------------------------
    //
    // FUNCTION: Print()
    //
    // DESCRIPTION: Displays the contents of this range object, for debugging
    //              purposes.
    // 
    // ---------------------------------------------------------------------------
    void Print();
};
